import os
import logging
from datetime import datetime
from logging.handlers import RotatingFileHandler
from typing import Dict, Optional
from contextvars import ContextVar
import threading
import json
import functools
import time

class AppLogger:
    """应用日志管理器"""
    _instance = None
    _loggers: Dict[str, logging.Logger] = {}
    _context: ContextVar[Dict] = ContextVar('logger_context', default={})

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super(AppLogger, cls).__new__(cls)
        return cls._instance

    def __init__(self):
        self.formatter = logging.Formatter(
            '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
        )

    def get_logger(
        self,
        name: str,
        log_dir: str,
        level: str = "INFO",
        max_bytes: int = 10*1024*1024,  # 10MB
        backup_count: int = 5,
        enable_console: bool = True
    ) -> logging.Logger:
        """
        获取或创建logger
        
        Args:
            name: 日志器名称
            log_dir: 日志目录
            level: 日志级别
            max_bytes: 单个日志文件最大大小
            backup_count: 备份文件数量
            enable_console: 是否启用控制台输出
        """
        if name in self._loggers:
            return self._loggers[name]

        # 创建日期目录
        date_str = datetime.now().strftime("%Y-%m-%d")
        daily_log_dir = os.path.join(log_dir, date_str)
        os.makedirs(daily_log_dir, exist_ok=True)

        # 创建logger
        logger = logging.getLogger(name)
        logger.setLevel(getattr(logging, level.upper()))
        logger.handlers.clear()

        # 文件处理器
        log_file = os.path.join(daily_log_dir, f'{name}.log')
        file_handler = RotatingFileHandler(
            log_file,
            maxBytes=max_bytes,
            backupCount=backup_count,
            encoding='utf-8'
        )
        file_handler.setFormatter(self.formatter)
        logger.addHandler(file_handler)

        # 控制台处理器
        if enable_console:
            console_handler = logging.StreamHandler()
            console_handler.setFormatter(self.formatter)
            logger.addHandler(console_handler)

        self._loggers[name] = logger
        return logger

    def setup_service_loggers(
        self,
        service_name: str,
        log_dir: str,
        log_config: dict
    ) -> Dict[str, logging.Logger]:
        """
        设置服务的所有日志器
        
        Args:
            service_name: 服务名称
            log_dir: 日志根目录
            log_config: 日志配置
        """
        loggers = {}
        for level in ['info', 'error', 'debug', 'warn']:
            logger_name = f"{service_name}.{level}"
            loggers[level] = self.get_logger(
                name=logger_name,
                log_dir=log_dir,
                level=level.upper(),
                max_bytes=log_config.get('max_size', 10*1024*1024),
                backup_count=log_config.get('backup_count', 5),
                enable_console=log_config.get('enable_console', True)
            )
        return loggers

    def get_context(self) -> Dict:
        """获取当前上下文"""
        return self._context.get()

    def set_context(self, **kwargs):
        """设置上下文信息"""
        context = self._context.get()
        context.update(kwargs)
        self._context.set(context)

    def clear_context(self):
        """清除上下文"""
        self._context.set({})

# 全局日志管理器实例
app_logger = AppLogger()

def setup_logging(
    log_dir: str,
    service_name: Optional[str] = None,
    **kwargs
) -> Dict[str, logging.Logger]:
    """
    设置日志配置的便捷函数
    
    Args:
        log_dir: 日志目录
        service_name: 服务名称（可选）
        **kwargs: 其他配置参数
    """
    # 处理参数名称不一致的问题
    if 'log_level' in kwargs:
        kwargs['level'] = kwargs.pop('log_level')

    if service_name:
        return app_logger.setup_service_loggers(
            service_name=service_name,
            log_dir=log_dir,
            log_config=kwargs
        )
    else:
        return {
            'default': app_logger.get_logger(
                name='app',
                log_dir=log_dir,
                **kwargs
            )
        } 

class StructuredFormatter(logging.Formatter):
    def format(self, record):
        # 基础信息
        log_data = {
            'timestamp': self.formatTime(record),
            'level': record.levelname,
            'logger': record.name,
            'message': record.getMessage(),
            'thread': threading.current_thread().name
        }
        
        # 添加上下文信息
        context = app_logger.get_context()
        if context:
            log_data['context'] = context
            
        # 添加异常信息
        if record.exc_info:
            log_data['exception'] = self.formatException(record.exc_info)
            
        return json.dumps(log_data, ensure_ascii=False) 

def log_function(logger=None):
    """函数执行日志装饰器"""
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            # 使用传入的logger或从函数属性中获取
            current_logger = logger or wrapper.__dict__.get('logger')
            if not current_logger:
                raise ValueError("Logger not set for function")
                
            start_time = time.time()
            func_name = func.__name__
            
            current_logger.debug(f"开始执行函数: {func_name}")
            try:
                result = func(*args, **kwargs)
                elapsed = time.time() - start_time
                current_logger.debug(f"函数 {func_name} 执行完成，耗时: {elapsed:.2f}秒")
                return result
            except Exception as e:
                elapsed = time.time() - start_time
                current_logger.error(f"函数 {func_name} 执行失败，耗时: {elapsed:.2f}秒，错误: {str(e)}")
                raise
        return wrapper
    return decorator 